/**
 * 绘制基本图元
 * @date   2011-3-28
 * @author tianye
 */
package cn.edu.dlut.WingGame.Graphic;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.opengles.GL10;

import cn.edu.dlut.WingGame.BaseType.WingColor;
import cn.edu.dlut.WingGame.BaseType.WingPoint;

public class GLShape {
	private float lineWidth = 1;// 线条宽度
	private float pointSize = 1;// 点的大小

	public void setLineWidth(float width) {
		lineWidth = width;
	}

	public void setPointSize(float size) {
		pointSize = size;
	}

	public void drawPoint(float x, float y, WingColor color) {
		ByteBuffer vbb = ByteBuffer.allocateDirect(8);
		vbb.order(ByteOrder.nativeOrder());
		FloatBuffer vertices = vbb.asFloatBuffer();
		vertices.put(x);
		vertices.put(y);
		vertices.position(0);

		if (color.hasAlpha())
			GLDevice.enableBlend();
		GLDevice.getGL().glVertexPointer(2, GL10.GL_FLOAT, 0, vertices);
		GLDevice.getGL().glEnableClientState(GL10.GL_VERTEX_ARRAY);
		GLDevice.getGL().glPointSize(pointSize);
		GLDevice.getGL().glColor4f(color.getRf(), color.getGf(), color.getBf(),
				color.getAf() * GLDevice.getAlpha());
		GLDevice.getGL().glDrawArrays(GL10.GL_POINTS, 0, 1);
		GLDevice.getGL().glDisableClientState(GL10.GL_VERTEX_ARRAY);
		if (color.hasAlpha())
			GLDevice.disableBlend();
	}

	public void drawLine(float x1, float y1, float x2, float y2, WingColor color) {
		ByteBuffer vbb = ByteBuffer.allocateDirect(16);
		vbb.order(ByteOrder.nativeOrder());
		FloatBuffer vertices = vbb.asFloatBuffer();

		vertices.put(x1);
		vertices.put(y1);
		vertices.put(x2);
		vertices.put(y2);
		vertices.position(0);
		if (color.hasAlpha())
			GLDevice.enableBlend();
		GLDevice.getGL().glVertexPointer(2, GL10.GL_FLOAT, 0, vertices);
		GLDevice.getGL().glEnableClientState(GL10.GL_VERTEX_ARRAY);
		GLDevice.getGL().glLineWidth(lineWidth);
		GLDevice.getGL().glColor4f(color.getRf(), color.getGf(), color.getBf(),
				color.getAf() * GLDevice.getAlpha());
		GLDevice.getGL().glDrawArrays(GL10.GL_LINES, 0, 2);
		GLDevice.getGL().glDisableClientState(GL10.GL_VERTEX_ARRAY);
		if (color.hasAlpha())
			GLDevice.disableBlend();
	}

	public void drawRect(float x1, float y1, float x2, float y2, WingColor color) {
		ByteBuffer vbb = ByteBuffer.allocateDirect(32);
		vbb.order(ByteOrder.nativeOrder());
		FloatBuffer vertices = vbb.asFloatBuffer();

		vertices.put(x1);
		vertices.put(y1);
		vertices.put(x2);
		vertices.put(y1);
		vertices.put(x2);
		vertices.put(y2);
		vertices.put(x1);
		vertices.put(y2);
		vertices.position(0);
		if (color.hasAlpha())
			GLDevice.enableBlend();
		GLDevice.getGL().glVertexPointer(2, GL10.GL_FLOAT, 0, vertices);
		GLDevice.getGL().glEnableClientState(GL10.GL_VERTEX_ARRAY);
		GLDevice.getGL().glLineWidth(lineWidth);
		GLDevice.getGL().glColor4f(color.getRf(), color.getGf(), color.getBf(),
				color.getAf() * GLDevice.getAlpha());
		GLDevice.getGL().glDrawArrays(GL10.GL_LINE_LOOP, 0, 4);
		GLDevice.getGL().glDisableClientState(GL10.GL_VERTEX_ARRAY);
		if (color.hasAlpha())
			GLDevice.disableBlend();
	}

	public void fillRect(float x1, float y1, float x2, float y2, WingColor color) {
		ByteBuffer vbb = ByteBuffer.allocateDirect(32);
		vbb.order(ByteOrder.nativeOrder());
		FloatBuffer vertices = vbb.asFloatBuffer();

		vertices.put(x1);
		vertices.put(y1);
		vertices.put(x1);
		vertices.put(y2);
		vertices.put(x2);
		vertices.put(y1);
		vertices.put(x2);
		vertices.put(y2);
		vertices.position(0);
		if (color.hasAlpha())
			GLDevice.enableBlend();
		GLDevice.getGL().glVertexPointer(2, GL10.GL_FLOAT, 0, vertices);
		GLDevice.getGL().glEnableClientState(GL10.GL_VERTEX_ARRAY);
		GLDevice.getGL().glColor4f(color.getRf(), color.getGf(), color.getBf(),
				color.getAf() * GLDevice.getAlpha());
		GLDevice.getGL().glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4);
		GLDevice.getGL().glDisableClientState(GL10.GL_VERTEX_ARRAY);
		if (color.hasAlpha())
			GLDevice.disableBlend();
	}

	public void drawPolygon(WingPoint[] pos, WingColor color) {
		ByteBuffer vbb = ByteBuffer.allocateDirect(8 * pos.length);
		vbb.order(ByteOrder.nativeOrder());
		FloatBuffer vertices = vbb.asFloatBuffer();

		for (int i = 0; i < pos.length; ++i) {
			vertices.put(pos[i].x);
			vertices.put(pos[i].y);
		}
		vertices.position(0);
		if (color.hasAlpha())
			GLDevice.enableBlend();
		GLDevice.getGL().glVertexPointer(2, GL10.GL_FLOAT, 0, vertices);
		GLDevice.getGL().glEnableClientState(GL10.GL_VERTEX_ARRAY);
		GLDevice.getGL().glLineWidth(lineWidth);
		GLDevice.getGL().glColor4f(color.getRf(), color.getGf(), color.getBf(),
				color.getAf() * GLDevice.getAlpha());
		GLDevice.getGL().glDrawArrays(GL10.GL_LINE_LOOP, 0, pos.length);
		GLDevice.getGL().glDisableClientState(GL10.GL_VERTEX_ARRAY);
		if (color.hasAlpha())
			GLDevice.disableBlend();
	}

	public void fillPolygon(WingPoint[] pos, WingColor color) {
		ByteBuffer vbb = ByteBuffer.allocateDirect(8 * pos.length * 3);
		vbb.order(ByteOrder.nativeOrder());
		FloatBuffer vertices = vbb.asFloatBuffer();
		WingPoint tpoint = new WingPoint();
		tpoint.x = (pos[0].x + pos[pos.length / 2].x + pos[pos.length / 4].x + pos[pos.length / 4 * 3].x) / 4;// 获取多边形的中心点【粗略获取】
		tpoint.y = (pos[0].y + pos[pos.length / 2].y + pos[pos.length / 4].y + pos[pos.length / 4 * 3].y) / 4;
		for (int i = 0; i < pos.length - 1; i++) {
			vertices.put(pos[i].x);
			vertices.put(pos[i].y);
			vertices.put(pos[i + 1].x);
			vertices.put(pos[i + 1].y);
			vertices.put(tpoint.x);
			vertices.put(tpoint.y);
		}
		vertices.put(pos[0].x);
		vertices.put(pos[0].y);
		vertices.put(pos[pos.length - 1].x);
		vertices.put(pos[pos.length - 1].y);
		vertices.put(tpoint.x);
		vertices.put(tpoint.y);
		vertices.position(0);
		if (color.hasAlpha())
			GLDevice.enableBlend();
		GLDevice.getGL().glVertexPointer(2, GL10.GL_FLOAT, 0, vertices);
		GLDevice.getGL().glEnableClientState(GL10.GL_VERTEX_ARRAY);
		GLDevice.getGL().glColor4f(color.getRf(), color.getGf(), color.getBf(),
				color.getAf() * GLDevice.getAlpha());
		GLDevice.getGL().glDrawArrays(GL10.GL_TRIANGLES, 0, pos.length * 3);
		GLDevice.getGL().glDisableClientState(GL10.GL_VERTEX_ARRAY);
		if (color.hasAlpha())
			GLDevice.disableBlend();
	}

	public void drawEllipse(float x1, float y1, float x2, float y2,
			WingColor color) {

		float a = (x2 - x1) / 2;
		float b = (y2 - y1) / 2;
		int count = (int) Math.ceil((a + b) / 4 + 16);
		WingPoint pos[] = new WingPoint[count * 2];
		float tx, ty, k;
		for (int i = 0; i < count; i++) {
			k = (float) Math.tan(3.141592653 / count * i);
			tx = (float) (a * b / Math.sqrt(b * b + a * a * k * k));
			if (i > count / 2)
				tx = -tx;
			ty = (float) (b * Math.sqrt((1 + tx / a) * (1 - tx / a)));
			pos[i] = new WingPoint(x1 + a + tx, y1 + b - ty);
			pos[count * 2 - 1 - i] = new WingPoint(x1 + a + tx, y1 + b + ty);
		}
		drawPolygon(pos, color);
	}

	public void fillEllipse(float x1, float y1, float x2, float y2,
			WingColor color) {

		float a = (x2 - x1) / 2;
		float b = (y2 - y1) / 2;
		int count = (int) Math.ceil((a + b) / 4 + 16);
		WingPoint pos[] = new WingPoint[count * 2];
		float tx, ty, k;
		for (int i = 0; i < count; i++) {
			k = (float) Math.tan(3.141592653 / count * i);
			tx = (float) (a * b / Math.sqrt(b * b + a * a * k * k));
			if (i > count / 2)
				tx = -tx;
			ty = (float) (b * Math.sqrt((1 + tx / a) * (1 - tx / a)));
			pos[i] = new WingPoint(x1 + a + tx, y1 + b - ty);
			pos[count * 2 - 1 - i] = new WingPoint(x1 + a + tx, y1 + b + ty);
		}
		fillPolygon(pos, color);
	}

	public void drawCircle(float x1, float y1, float r, WingColor color) {
		float xx1 = x1 - r;
		float yy1 = y1 + r;
		float xx2 = x1 + r;
		float yy2 = y1 - r;
		drawEllipse(xx1, yy1, xx2, yy2, color);
	}

	public void fillCircle(float x1, float y1, float r, WingColor color) {
		float xx1 = x1 - r;
		float yy1 = y1 + r;
		float xx2 = x1 + r;
		float yy2 = y1 - r;
		fillEllipse(xx1, yy1, xx2, yy2, color);
	}
}
